﻿/****************************************************************
*   作者：qq918
*   创建时间：2017/12/20 17:36:59
*   描述说明：
*   
*   资源更新管理器
*****************************************************************/

using System;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

namespace Model
{
    /// <summary>
    /// AB包下载管理类
    /// </summary>
    public class AssetBundleDownloadManager : Singleton<AssetBundleDownloadManager>
    {
        private string WebURI = "";

        /// <summary>
        /// 远程资源服务器中的版本信息
        /// </summary>
        public VersionConfig WebVersionConfig { get; private set; }

        /// <summary>
        /// 需要更新的bundles
        /// </summary>
        public Queue<string> bundles;

        /// <summary>
        /// 需要更新的总大小
        /// </summary>
        public long TotalSize;

        /// <summary>
        /// 已经下载完成的bundles
        /// </summary>
        public HashSet<string> downlaodedBundles;

        /// <summary>
        /// 正在下载的bundle
        /// </summary>
        public string downloadingBundle;

        /// <summary>
        /// 资源都OK的回调
        /// </summary>
        public Action OnSuccess;

        /// <summary>
        /// 错误回调
        /// </summary>
        public Action<Exception> OnError;

        /// <summary>
        /// 唤醒就和服务器对比资源
        /// </summary>
        /// <param name="uri"></param>
        public async void Awake(string uri)
        {
            this.bundles = new Queue<string>();
            this.downlaodedBundles = new HashSet<string>();
            this.WebURI = uri;
            try
            {
                string versionUri = $"{uri}/{PathHelper.GetCurrentPlatform()}/Version.json";
                string versionConfigStr = await HttpHelper.GetToStringAsyn(versionUri);
                WebVersionConfig = JsonHelper.FromString(versionConfigStr);

                //Debug.Log("WebVersion: " + JsonHelper.ToJson(WebVersionConfig));

                string localVersionConfigPath = Path.Combine(PathHelper.AppHotfixResPath, "Version.json");

                //Debug.Log("LocalVersionPath:" + localVersionConfigPath);

                if (!File.Exists(localVersionConfigPath))
                {
                    foreach (var item in this.WebVersionConfig.FileVersionInfos)
                    {
                        if (item.File == "Version.json")
                            continue;

                        this.bundles.Enqueue(item.File);
                        this.TotalSize += item.Size;
                    }
                }
                else
                {
                    // 本地有版本json文件
                    string json = File.ReadAllText(localVersionConfigPath);
                    VersionConfig localVersionConfig = JsonHelper.FromString(json);
                    //Debug.Log("LocalVersion:" + localVersionConfig.ToJson());
                    // 先删除服务端没有的AB包
                    foreach (FileVersionInfo item in localVersionConfig.FileVersionInfos)
                    {
                        if (WebVersionConfig.Dictionary.ContainsKey(item.File)) continue;

                        string abPath = Path.Combine(PathHelper.AppHotfixResPath, item.File);
                        File.Delete(abPath);
                    }

                    // 筛选出需要下载的AB包
                    foreach (var webFileVersion in this.WebVersionConfig.FileVersionInfos)
                    {
                        // 对比本地AB包的MD5，忽略相同的值和Version.json文件。
                        FileVersionInfo localFileVersionInfo;
                        if (localVersionConfig.Dictionary.TryGetValue(webFileVersion.File, out localFileVersionInfo))
                        {
                            if (localFileVersionInfo.MD5 == webFileVersion.MD5)
                                continue;
                        }

                        if (webFileVersion.File == "Version.json")
                            continue;

                        this.bundles.Enqueue(webFileVersion.File);
                        this.TotalSize += webFileVersion.Size;
                    }

                }

                // 如果没有需要下载的AB包，就结束当前方法。
                if (this.bundles.Count == 0)
                {
                    OnSuccess?.Invoke();
                    return;
                }

                //Debug.Log($"need download bundles: {this.bundles.ToJson()}");

                // 开始更新
                StartUpdate();
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
                OnError?.Invoke(e);
            }
            OnSuccess?.Invoke();
        }

        /// <summary>
        /// 开始更新AB包
        /// </summary>
        /// <returns></returns>
        public void StartUpdate()
        {
            while (true)
            {
                if (this.bundles.Count == 0)
                    break;

                this.downloadingBundle = this.bundles.Dequeue();

                while (true)
                {
                    try
                    {
                        string webFilePath = $"{this.WebURI}/{PathHelper.GetCurrentPlatform()}/{this.downloadingBundle}";
                        string saveDir = PathHelper.AppHotfixResPath;
                        Debug.Log($"webFilePath: {webFilePath}，savePath: {saveDir}");

                        if (!Directory.Exists(saveDir))
                        {
                            Directory.CreateDirectory(saveDir);
                        }

                        HttpHelper.DownloadFile(webFilePath, saveDir + "/" + this.downloadingBundle);

                        //Debug.Log(this.downloadingBundle + " :更新成功！");
                    }
                    catch (Exception e)
                    {
                        Debug.LogError($"download bundle error: {e.Message} ");
                        OnError?.Invoke(e);
                        return;
                    }
                    break;
                }

                this.downlaodedBundles.Add(this.downloadingBundle);
                this.downloadingBundle = "";
            }

            // 全部更新完成后，更新版本文件。
            using (FileStream fs = new FileStream(Path.Combine(PathHelper.AppHotfixResPath, "Version.json"), FileMode.Create, FileAccess.Write))
            using (StreamWriter sw = new StreamWriter(fs))
            {
                sw.Write(JsonHelper.ToJson(this.WebVersionConfig));
            }

        }
    }
}